import base64
import json
import requests
import logging
from django.conf import settings
from django.core.files.uploadedfile import UploadedFile
from typing import Dict, List, Optional, Tuple
import re

logger = logging.getLogger(__name__)

class BaiduAIService:
    """百度AI服务类 - 专门用于医疗图片识别和OCR"""
    
    def __init__(self):
        # 使用用户提供的API Key
        self.api_key = "M44uo38ABN6MOR24m6CyiUS7"
        # 注意：您需要提供正确的Secret Key，通常与API Key不同
        # 请到百度AI控制台获取正确的Secret Key
        self.secret_key = "8dAVdzxvTR6zXtDVbzBFMpZKmGeGRQN4"  # 请替换为您的实际Secret Key
        self.base_url = "https://aip.baidubce.com/rest/2.0"
        self.token_url = "https://aip.baidubce.com/oauth/2.0/token"
        self.access_token = None
        
    def get_access_token(self) -> str:
        """获取百度AI访问令牌"""
        if self.access_token:
            return self.access_token
        
        # 如果Secret Key未正确配置，返回模拟token用于测试
        if self.secret_key == "8dAVdzxvTR6zXtDVbzBFMpZKmGeGRQN4":
            logger.warning("百度AI Secret Key未配置，使用模拟服务")
            self.access_token = "mock_token_for_testing"
            return self.access_token
            
        params = {
            'grant_type': 'client_credentials',
            'client_id': self.api_key,
            'client_secret': self.secret_key
        }
        
        try:
            response = requests.post(self.token_url, params=params)
            response.raise_for_status()
            data = response.json()
            self.access_token = data.get('access_token')
            return self.access_token
        except Exception as e:
            logger.error(f"获取百度AI访问令牌失败: {e}")
            raise
    
    def image_to_base64(self, image_file) -> str:
        """将图片文件转换为base64编码"""
        if isinstance(image_file, UploadedFile):
            image_data = image_file.read()
        else:
            with open(image_file.path, 'rb') as f:
                image_data = f.read()
        
        return base64.b64encode(image_data).decode('utf-8')

class MedicalImageRecognitionService(BaiduAIService):
    """医疗图片识别服务"""
    
    def recognize_skin_condition(self, image_file) -> Dict:
        """识别皮肤病症状"""
        # 如果使用模拟服务，返回模拟结果
        if self.secret_key == "YOUR_SECRET_KEY_HERE":
            return self._get_mock_skin_result()
            
        access_token = self.get_access_token()
        url = f"{self.base_url}/image-classify/v2/advanced_general"
        
        params = {'access_token': access_token}
        image_base64 = self.image_to_base64(image_file)
        
        data = {
            'image': image_base64,
            'top_num': 5,  # 返回前5个结果
            'filter_threshold': 0.7,  # 置信度阈值
            'baike_num': 1  # 百科信息数量
        }
        
        try:
            response = requests.post(url, params=params, data=data)
            response.raise_for_status()
            result = response.json()
            
            # 解析结果，匹配医疗相关症状
            medical_symptoms = self._parse_medical_symptoms(result)
            return {
                'success': True,
                'raw_result': result,
                'medical_symptoms': medical_symptoms,
                'suggested_diseases': self._suggest_diseases(medical_symptoms),
                'suggested_department': self._suggest_department(medical_symptoms)
            }
        except Exception as e:
            logger.error(f"皮肤病识别失败: {e}")
            return {'success': False, 'error': str(e)}
    
    def _get_mock_skin_result(self) -> Dict:
        """获取模拟的皮肤识别结果"""
        return {
            'success': True,
            'raw_result': {'result': [{'keyword': '皮肤红疹', 'score': 0.85}]},
            'medical_symptoms': [
                {'keyword': '皮肤红疹', 'confidence': 0.85, 'category': '皮肤'}
            ],
            'suggested_diseases': ['湿疹', '过敏性皮炎', '接触性皮炎'],
            'suggested_department': '皮肤科'
        }
    
    def recognize_oral_condition(self, image_file) -> Dict:
        """识别口腔症状"""
        access_token = self.get_access_token()
        url = f"{self.base_url}/image-classify/v2/advanced_general"
        
        params = {'access_token': access_token}
        image_base64 = self.image_to_base64(image_file)
        
        data = {
            'image': image_base64,
            'top_num': 5,
            'filter_threshold': 0.7,
            'baike_num': 1
        }
        
        try:
            response = requests.post(url, params=params, data=data)
            response.raise_for_status()
            result = response.json()
            
            # 解析口腔相关症状
            oral_symptoms = self._parse_oral_symptoms(result)
            return {
                'success': True,
                'raw_result': result,
                'oral_symptoms': oral_symptoms,
                'suggested_diseases': self._suggest_oral_diseases(oral_symptoms),
                'suggested_department': '口腔科'
            }
        except Exception as e:
            logger.error(f"口腔症状识别失败: {e}")
            return {'success': False, 'error': str(e)}
    
    def recognize_eye_condition(self, image_file) -> Dict:
        """识别眼部症状"""
        access_token = self.get_access_token()
        url = f"{self.base_url}/image-classify/v2/advanced_general"
        
        params = {'access_token': access_token}
        image_base64 = self.image_to_base64(image_file)
        
        data = {
            'image': image_base64,
            'top_num': 5,
            'filter_threshold': 0.7,
            'baike_num': 1
        }
        
        try:
            response = requests.post(url, params=params, data=data)
            response.raise_for_status()
            result = response.json()
            
            # 解析眼部相关症状
            eye_symptoms = self._parse_eye_symptoms(result)
            return {
                'success': True,
                'raw_result': result,
                'eye_symptoms': eye_symptoms,
                'suggested_diseases': self._suggest_eye_diseases(eye_symptoms),
                'suggested_department': '眼科'
            }
        except Exception as e:
            logger.error(f"眼部症状识别失败: {e}")
            return {'success': False, 'error': str(e)}
    
    def _parse_medical_symptoms(self, result: Dict) -> List[Dict]:
        """解析医疗症状"""
        symptoms = []
        if 'result' in result:
            for item in result['result']:
                keyword = item.get('keyword', '')
                score = item.get('score', 0)
                
                # 医疗相关关键词匹配
                if self._is_medical_related(keyword):
                    symptoms.append({
                        'keyword': keyword,
                        'confidence': score,
                        'category': self._categorize_symptom(keyword)
                    })
        return symptoms
    
    def _parse_oral_symptoms(self, result: Dict) -> List[Dict]:
        """解析口腔症状"""
        oral_keywords = ['龋齿', '溃疡', '牙龈', '牙齿', '口腔', '舌头', '口疮', '牙痛']
        return self._filter_by_keywords(result, oral_keywords, '口腔')
    
    def _parse_eye_symptoms(self, result: Dict) -> List[Dict]:
        """解析眼部症状"""
        eye_keywords = ['眼睛', '眼部', '结膜', '角膜', '视力', '眼红', '眼痛', '眼肿']
        return self._filter_by_keywords(result, eye_keywords, '眼部')
    
    def _filter_by_keywords(self, result: Dict, keywords: List[str], category: str) -> List[Dict]:
        """根据关键词过滤结果"""
        symptoms = []
        if 'result' in result:
            for item in result['result']:
                keyword = item.get('keyword', '')
                score = item.get('score', 0)
                
                if any(kw in keyword for kw in keywords):
                    symptoms.append({
                        'keyword': keyword,
                        'confidence': score,
                        'category': category
                    })
        return symptoms
    
    def _is_medical_related(self, keyword: str) -> bool:
        """判断是否为医疗相关关键词"""
        medical_keywords = [
            '皮肤', '红疹', '湿疹', '皮炎', '过敏', '痘痘', '斑点', '痣',
            '口腔', '牙齿', '牙龈', '溃疡', '龋齿', '牙痛',
            '眼睛', '眼部', '结膜', '角膜', '视力', '眼红',
            '伤口', '炎症', '肿胀', '疼痛', '出血'
        ]
        return any(med_kw in keyword for med_kw in medical_keywords)
    
    def _categorize_symptom(self, keyword: str) -> str:
        """症状分类"""
        if any(kw in keyword for kw in ['皮肤', '红疹', '湿疹', '皮炎', '过敏', '痘痘']):
            return '皮肤'
        elif any(kw in keyword for kw in ['口腔', '牙齿', '牙龈', '溃疡', '龋齿']):
            return '口腔'
        elif any(kw in keyword for kw in ['眼睛', '眼部', '结膜', '角膜', '视力']):
            return '眼部'
        else:
            return '其他'
    
    def _suggest_diseases(self, symptoms: List[Dict]) -> List[str]:
        """根据症状建议疾病"""
        disease_map = {
            '湿疹': ['湿疹', '过敏性皮炎', '接触性皮炎'],
            '红疹': ['荨麻疹', '过敏性皮炎', '湿疹'],
            '痘痘': ['痤疮', '毛囊炎', '皮脂腺炎'],
            '溃疡': ['口腔溃疡', '胃溃疡', '十二指肠溃疡'],
            '龋齿': ['龋齿', '牙髓炎', '根尖周炎'],
            '眼红': ['结膜炎', '角膜炎', '干眼症']
        }
        
        suggested = set()
        for symptom in symptoms:
            keyword = symptom['keyword']
            for disease, variants in disease_map.items():
                if disease in keyword:
                    suggested.update(variants)
        
        return list(suggested)
    
    def _suggest_oral_diseases(self, symptoms: List[Dict]) -> List[str]:
        """建议口腔疾病"""
        return ['龋齿', '口腔溃疡', '牙龈炎', '牙周炎', '根尖周炎']
    
    def _suggest_eye_diseases(self, symptoms: List[Dict]) -> List[str]:
        """建议眼部疾病"""
        return ['结膜炎', '角膜炎', '干眼症', '青光眼', '白内障']
    
    def _suggest_department(self, symptoms: List[Dict]) -> str:
        """建议科室"""
        if not symptoms:
            return '内科'
        
        categories = [s['category'] for s in symptoms]
        if '皮肤' in categories:
            return '皮肤科'
        elif '口腔' in categories:
            return '口腔科'
        elif '眼部' in categories:
            return '眼科'
        else:
            return '内科'

class MedicalOCRService(BaiduAIService):
    """医疗文档OCR服务"""
    
    def extract_text_from_document(self, image_file) -> Dict:
        """从医疗文档中提取文本"""
        # 如果使用模拟服务，返回模拟结果
        if self.secret_key == "YOUR_SECRET_KEY_HERE":
            return self._get_mock_ocr_result()
            
        access_token = self.get_access_token()
        url = f"{self.base_url}/ocr/v1/accurate_basic"
        
        params = {'access_token': access_token}
        image_base64 = self.image_to_base64(image_file)
        
        data = {
            'image': image_base64,
            'detect_direction': True,  # 检测文字方向
            'probability': True  # 返回置信度
        }
        
        try:
            response = requests.post(url, params=params, data=data)
            response.raise_for_status()
            result = response.json()
            
            # 提取和结构化文本
            extracted_text = self._extract_text(result)
            structured_data = self._parse_medical_data(extracted_text)
            medical_indicators = self._extract_medical_indicators(extracted_text)
            
            return {
                'success': True,
                'raw_result': result,
                'extracted_text': extracted_text,
                'structured_data': structured_data,
                'medical_indicators': medical_indicators,
                'abnormal_values': self._find_abnormal_values(medical_indicators)
            }
        except Exception as e:
            logger.error(f"医疗文档OCR失败: {e}")
            return {'success': False, 'error': str(e)}
    
    def _get_mock_ocr_result(self) -> Dict:
        """获取模拟的OCR识别结果"""
        mock_indicators = [
            {
                'name': '白细胞计数',
                'value': 8.5,
                'unit': '×10⁹/L',
                'normal_range': (4.0, 10.0),
                'is_normal': True,
                'status': 'normal'
            },
            {
                'name': '血红蛋白',
                'value': 120,
                'unit': 'g/L',
                'normal_range': (130, 175),
                'is_normal': False,
                'status': 'abnormal'
            }
        ]
        
        return {
            'success': True,
            'raw_result': {'words_result': [{'words': '白细胞计数：8.5×10⁹/L'}, {'words': '血红蛋白：120g/L'}]},
            'extracted_text': '白细胞计数：8.5×10⁹/L\n血红蛋白：120g/L',
            'structured_data': {'白细胞计数': '8.5', '血红蛋白': '120'},
            'medical_indicators': mock_indicators,
            'abnormal_values': [mock_indicators[1]]  # 血红蛋白异常
        }
    
    def extract_table_from_report(self, image_file) -> Dict:
        """从报告中提取表格数据"""
        access_token = self.get_access_token()
        url = f"{self.base_url}/ocr/v1/table"
        
        params = {'access_token': access_token}
        image_base64 = self.image_to_base64(image_file)
        
        data = {
            'image': image_base64,
            'table_type': 'excel'  # 表格类型
        }
        
        try:
            response = requests.post(url, params=params, data=data)
            response.raise_for_status()
            result = response.json()
            
            return {
                'success': True,
                'raw_result': result,
                'table_data': self._parse_table_data(result)
            }
        except Exception as e:
            logger.error(f"表格OCR失败: {e}")
            return {'success': False, 'error': str(e)}
    
    def _extract_text(self, result: Dict) -> str:
        """提取纯文本"""
        text_parts = []
        if 'words_result' in result:
            for item in result['words_result']:
                text_parts.append(item.get('words', ''))
        return '\n'.join(text_parts)
    
    def _parse_medical_data(self, text: str) -> Dict:
        """解析医疗数据"""
        # 血常规指标正则表达式
        blood_test_patterns = {
            '白细胞计数': r'白细胞计数[：:]\s*(\d+(?:\.\d+)?)\s*×?10?\^?9?/L',
            '红细胞计数': r'红细胞计数[：:]\s*(\d+(?:\.\d+)?)\s*×?10?\^?12?/L',
            '血红蛋白': r'血红蛋白[：:]\s*(\d+(?:\.\d+)?)\s*g/L',
            '血小板计数': r'血小板计数[：:]\s*(\d+(?:\.\d+)?)\s*×?10?\^?9?/L',
            '中性粒细胞': r'中性粒细胞[：:]\s*(\d+(?:\.\d+)?)%',
            '淋巴细胞': r'淋巴细胞[：:]\s*(\d+(?:\.\d+)?)%'
        }
        
        # 影像学检查正则表达式
        imaging_patterns = {
            '双肺纹理': r'双肺纹理(增粗|清晰|模糊)',
            '心脏大小': r'心脏大小(正常|增大|缩小)',
            '胸腔积液': r'(有|无)胸腔积液',
            '结节': r'(有|无)结节'
        }
        
        parsed_data = {}
        
        # 解析血常规
        for indicator, pattern in blood_test_patterns.items():
            match = re.search(pattern, text)
            if match:
                parsed_data[indicator] = match.group(1)
        
        # 解析影像学
        for indicator, pattern in imaging_patterns.items():
            match = re.search(pattern, text)
            if match:
                parsed_data[indicator] = match.group(1)
        
        return parsed_data
    
    def _extract_medical_indicators(self, text: str) -> List[Dict]:
        """提取医疗指标"""
        indicators = []
        
        # 常见的医疗指标及其正常范围
        indicator_ranges = {
            '白细胞计数': {'normal': (4.0, 10.0), 'unit': '×10⁹/L'},
            '红细胞计数': {'normal': (4.3, 5.8), 'unit': '×10¹²/L'},
            '血红蛋白': {'normal': (130, 175), 'unit': 'g/L'},
            '血小板计数': {'normal': (125, 350), 'unit': '×10⁹/L'},
            '中性粒细胞': {'normal': (50, 70), 'unit': '%'},
            '淋巴细胞': {'normal': (20, 40), 'unit': '%'}
        }
        
        for indicator, config in indicator_ranges.items():
            pattern = f'{indicator}[：:]\\s*(\\d+(?:\\.\\d+)?)'
            match = re.search(pattern, text)
            if match:
                value = float(match.group(1))
                normal_range = config['normal']
                
                indicators.append({
                    'name': indicator,
                    'value': value,
                    'unit': config['unit'],
                    'normal_range': normal_range,
                    'is_normal': normal_range[0] <= value <= normal_range[1],
                    'status': 'normal' if normal_range[0] <= value <= normal_range[1] else 'abnormal'
                })
        
        return indicators
    
    def _find_abnormal_values(self, indicators: List[Dict]) -> List[Dict]:
        """找出异常值"""
        return [indicator for indicator in indicators if not indicator['is_normal']]
    
    def _parse_table_data(self, result: Dict) -> Dict:
        """解析表格数据"""
        # 这里需要根据百度OCR表格识别的具体返回格式来解析
        # 暂时返回原始结果
        return result.get('result', {})

class MultiModalAnalysisService:
    """多模态分析服务"""
    
    def __init__(self):
        self.image_service = MedicalImageRecognitionService()
        self.ocr_service = MedicalOCRService()
    
    def analyze_consultation(self, image_file=None, document_file=None, 
                           symptom_description: str = "") -> Dict:
        """综合分析问诊数据"""
        analysis_result = {
            'image_analysis': None,
            'document_analysis': None,
            'symptom_analysis': None,
            'comprehensive_analysis': None,
            'recommendations': []
        }
        
        # 图片分析
        if image_file:
            image_type = self._detect_image_type(image_file)
            if image_type == 'skin':
                analysis_result['image_analysis'] = self.image_service.recognize_skin_condition(image_file)
            elif image_type == 'oral':
                analysis_result['image_analysis'] = self.image_service.recognize_oral_condition(image_file)
            elif image_type == 'eye':
                analysis_result['image_analysis'] = self.image_service.recognize_eye_condition(image_file)
        
        # 文档分析
        if document_file:
            analysis_result['document_analysis'] = self.ocr_service.extract_text_from_document(document_file)
        
        # 症状文本分析
        if symptom_description:
            analysis_result['symptom_analysis'] = self._analyze_symptom_text(symptom_description)
        
        # 综合分析
        analysis_result['comprehensive_analysis'] = self._comprehensive_analysis(analysis_result)
        analysis_result['recommendations'] = self._generate_recommendations(analysis_result)
        
        return analysis_result
    
    def _detect_image_type(self, image_file) -> str:
        """检测图片类型"""
        # 这里可以通过文件名、EXIF信息等来判断图片类型
        # 暂时返回默认类型
        return 'skin'
    
    def _analyze_symptom_text(self, text: str) -> Dict:
        """分析症状文本"""
        # 简单的关键词匹配
        symptom_keywords = {
            '疼痛': ['疼痛', '痛', '疼'],
            '发热': ['发热', '发烧', '体温高'],
            '咳嗽': ['咳嗽', '咳'],
            '头痛': ['头痛', '头疼'],
            '恶心': ['恶心', '想吐'],
            '呕吐': ['呕吐', '吐']
        }
        
        found_symptoms = []
        for symptom, keywords in symptom_keywords.items():
            if any(keyword in text for keyword in keywords):
                found_symptoms.append(symptom)
        
        return {
            'detected_symptoms': found_symptoms,
            'text': text
        }
    
    def _comprehensive_analysis(self, analysis_result: Dict) -> Dict:
        """综合分析"""
        # 这里可以根据图片分析、文档分析、症状分析的结果进行综合判断
        return {
            'urgency_level': 'medium',
            'suggested_department': '内科',
            'confidence_score': 0.8
        }
    
    def _generate_recommendations(self, analysis_result: Dict) -> List[str]:
        """生成建议"""
        recommendations = []
        
        if analysis_result['image_analysis']:
            recommendations.append("建议尽快到相关科室进行详细检查")
        
        if analysis_result['document_analysis'] and analysis_result['document_analysis'].get('abnormal_values'):
            recommendations.append("检测结果存在异常值，建议咨询专科医生")
        
        return recommendations
